

#include "mef.h"
#include <iostream>
#include "solid.h"
#include "hedmodel.h"
#include "face.h"
#include "loop.h"
#include "point.h"
#include "vertex.h"
#include "edge.h"
#include "halfedge.h"
#include <assert.h>


MEF::MEF(HEDModel& _model, int _s, int _v1, int _v3, int _f2)
: he1( NULL )
, he2( NULL )
, f( _f2 )
{
  Vertex* vtx1 = _model.getVertex(_v1);
  Vertex* vtx2 = _model.getVertex(_v3);
  double x1 = vtx1->getPoint()->getX();
  double y1 = vtx1->getPoint()->getY();
  double z1 = vtx1->getPoint()->getZ();
  double x2 = vtx2->getPoint()->getX();
  double y2 = vtx2->getPoint()->getY();
  double z2 = vtx2->getPoint()->getZ();
  //HalfEdge* h1 = _model.getHalfEdge(vtx1,x2,y2,z2);
  //HalfEdge* h2 = _model.getHalfEdge(vtx2,x1,y1,z1);
  HalfEdge* h1 = _model.getHalfEdgeNEW(vtx1,x2,y2,z2);
  HalfEdge* h2 = _model.getHalfEdgeNEW(vtx2,x1,y1,z1);
  // checks if MEF starts with he1 the loop area is positive or negative
  double area = 0.0;
  HalfEdge* he = h1;
  while(he != h2)
  {
    std::cout << ".V = " << he->getVtx()->getVertexno() << std::endl;
    Point* pti  = he->getVtx()->getPoint();
    Point* ptii = he->getNxt()->getVtx()->getPoint();
    double xi = pti->getX();
    double yi = pti->getY();
    double xii = ptii->getX();
    double yii = ptii->getY();
    area += (xi*yii - xii*yi);
    he = he->getNxt();
  }
  std::cout << ".V = " << he->getVtx()->getVertexno() << std::endl;
  Point* pti  = he->getVtx()->getPoint();
  Point* ptii = h1->getVtx()->getPoint();
  double xi = pti->getX();
  double yi = pti->getY();
  double xii = ptii->getX();
  double yii = ptii->getY();
  area += (xi*yii - xii*yi);
  std::cout << ".area = " << area << std::endl;
  if( area < 0.0)
  {
    h2 = h1;
    h1 = he;
  }
  //h1 = h1->getPrv()->mate();
  //h2 = h2->getPrv()->mate();
  int nVtx1 = h1->getVtx()->getVertexno();
  int nVtx2 = h1->mate()->getVtx()->getVertexno();
  int nVtx3 = h2->getVtx()->getVertexno();
  int nVtx4 = h2->mate()->getVtx()->getVertexno();
  int nFct = h1->getLoop()->getFace()->getFaceno();
  int nFct2 = h2->getLoop()->getFace()->getFaceno();
  if (nFct != nFct2)
    assert(true);
  this->checksInputData(_model, _s, nFct, nVtx1, nVtx2, nVtx3, nVtx4);
}


MEF::MEF(HEDModel& _model, int _s, int _f1, int _v1, int _v2, int _v3, int _v4, int _f2)
: he1( NULL )
, he2( NULL )
, f( _f2 )
{
  this->checksInputData(_model, _s, _f1, _v1, _v2, _v3, _v4);
}


MEF::MEF(HalfEdge* _he1, HalfEdge* _he2, int _f)
: he1( _he1 )
, he2( _he2 )
, f( _f )
{

}



void
MEF::execute()
{
  std::cout << "\nMEF::execute() \n";
  Solid* solid = he1->getLoop()->getFace()->getSolid();
  Face* newface = new Face(solid);
  Edge* newedge = new Edge(solid);
  Loop* newloop = new Loop(newface);
  newface->setFaceno(f);
  newface->setFlout(newloop);
  HalfEdge* he = he1;
  while(he != he2)
  {
    he->setWloop(newloop);
    he = he->getNxt();
  }
  HalfEdge* nhe1 = newedge->addhe(he2->getVtx(), he1, MINUS);
  HalfEdge* nhe2 = newedge->addhe(he1->getVtx(), he2, PLUS);
  nhe1->getPrv()->setNxt(nhe2);
  nhe2->getPrv()->setNxt(nhe1);
  HalfEdge* temp = nhe1->getPrv();
  nhe1->setPrv(nhe2->getPrv());
  nhe2->setPrv(temp);
  newloop->setLedg(nhe1);
  he2->getLoop()->setLedg(nhe2);
}



void
MEF::unExecute()
{
  std::cout << "\nMEF::unExecute() NOT IMPLEMENTED!\n";
}


void
MEF::checksInputData(HEDModel& _model, int _s, int _f1, int _v1, int _v2, int _v3, int _v4)
{
  Solid* oldsolid = NULL;
  Face* oldface1 = NULL;
  if((oldsolid = _model.getsolid(_s)) == NULL)
  {
    std::cout << "mef: solid " << _s << " not found. \n";
    //return(ERROR);
  }
  if( (oldface1 = _model.fface(oldsolid,_f1)) == NULL)
  {
    std::cout << "mef: face " << _f1 << " not found in solid " << _s << ". \n";
    //return(ERROR);
  }
  if( (he1 = _model.fhe(oldface1,_v1, _v2)) == NULL)
  {
    std::cout << "mef: edge " << _v1 << " - " << _v2 << " not found in face " << _f1 << ". \n";
    //return(ERROR);
  }
  if( (he2 = _model.fhe(oldface1,_v3, _v4)) == NULL)
  {
    std::cout << "mef: edge " << _v3 << " - " << _v4 << " not found in face " << _f1 << ". \n";
    //return(ERROR);
  }
  //this->lmef(he1, he2, f2);
}
